package com.lili.core.bridge;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.context.ApplicationContext;

import com.lili.core.bridge.annotation.Bean;
import com.lili.core.bridge.annotation.Context;

/**
 * Proxy class for module interface.
 */
public class ModuleProxy implements InvocationHandler {

	/**
	 * Create instance of ModuleProxy.
	 *
	 * @param moduleType
	 * @param context
	 * @return
	 */
	static Object newProxyInstance(Class<?> moduleType,
			ApplicationContext context) {
		if (!moduleType.isInterface()) {
			throw new IllegalArgumentException(moduleType.getName()
					+ " is not an interface");
		}
		return Proxy.newProxyInstance(moduleType.getClassLoader(),
				new Class<?>[] { moduleType }, new ModuleProxy(context));
	}

	/**
	 *
	 * @param context
	 */
	private ModuleProxy(ApplicationContext context) {
		_context = context;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {

		if (method.isAnnotationPresent(Context.class)) {
			if (method.getReturnType().isAssignableFrom(
					ApplicationContext.class)) {
				return _context;
			}
			throw new UnsupportedOperationException(
					"The return type should be assignable from "
							+ ApplicationContext.class.getName());
		}
		if (method.isAnnotationPresent(Bean.class)) {
			return _context.getBean(method.getAnnotation(Bean.class).value(),
					method.getReturnType());
		}

		return null;
	}

	//

	ApplicationContext getContext() {
		return _context;
	}

	private ApplicationContext _context;
}
